package org.syx.droid.telnet.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import android.os.Handler;
import android.util.Log;

/**
 * This is in-charge of reading the InputStream of a client {@link Socket}, and
 * responding to the client appropriately.
 * 
 * @author cesardepadua
 * 
 */
public class SocketWatcher implements Runnable {
	
	private Handler handler;
	
	private Socket client;
	
	private PrintWriter w;
	
	private BufferedReader r;
	
	/**
	 * Made private so that processes will be used.
	 * 
	 * @param s
	 *            The {@link Socket} to be processed.
	 */
	private SocketWatcher (Socket s, Handler h) {
	
		Log.i ("SocketWatcher", "Creating new SocketWatcher");
		this.client = s;
		this.handler = h;
		this.w = null;
		this.r = null;
	}
	
	/**
	 * @param s
	 *            The {@link Socket} to be processed.
	 * @return An instance of {@link SocketWatcher} that `processes` the
	 *         {@link Socket}, `s`.
	 */
	public static SocketWatcher create (Handler h, Socket s) {
	
		Log.i ("SocketWatcher", "Creating new instance of SocketWatcher");
		if (s != null)
			return new SocketWatcher (s, h);
		else
			throw new NullPointerException ();
	}
	
	@Override
	public void run () {
	
		Log.i ("SocketWatcher", "Starting new SocketWatcher");
		this.readInput ();
	}
	
	/**
	 * Keep reading the input of the client until it receives `null` or "end".
	 */
	private void readInput () {
	
		w = null;
		r = null;
		try {
			w = new PrintWriter (this.client.getOutputStream ());
			r = new BufferedReader (new InputStreamReader (
					this.client.getInputStream ()));
			
			String message;
			while ((message = r.readLine ()) != null && !message.equals ("end")) {
				Log.i ("Message Received: ", message);
				this.handler.post (TextAppender.Factory.getInstance ()
						.createJob (message));
			}
			
		} catch (IOException e) {
			
			Log.e ("TelnetProcessor", "Error: ", e);
			
		} finally {
			
			if (w != null)
				w.close ();
			
			try {
				if (r != null)
					r.close ();
			} catch (IOException e) {
				Log.e ("TelnetProcessor", "ERROR: ", e);
			}
			
			try {
				if (this.client != null)
					this.client.close ();
			} catch (IOException e) {
				Log.e ("TelnetProcessor", "ERROR: ", e);
			}
		}
	}
	
}
